package com.polaris.live.utils.photo

import android.animation.Animator
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.util.AttributeSet
import android.view.MotionEvent
import com.github.chrisbanes.photoview.PhotoView

/**
 * DragPhotoView
 * @author Created by 天晴 on 2024/1/11 9:50
 * @since 1.0.0
 **/
class DragPhotoView @JvmOverloads constructor(
    context: Context?,
    attr: AttributeSet? = null,
    defStyle: Int = 0
) : PhotoView(context, attr, defStyle) {

    private var mPaint: Paint = Paint()

    // downX
    private var mDownX = 0f

    // down Y
    private var mDownY = 0f

    private var mTranslateY = 0f
    private var mTranslateX = 0f
    private var mScale = 1f
    private var mWidth = 0
    private var mHeight = 0
    private var mMinScale = 0.5f
    private var mAlpha = 255
    private val MAX_TRANSLATE_Y = 400

    private val DURATION: Long = 300
    private var canFinish = false
    private var isAnimate = false

    //is event on PhotoView
    private var isTouchEvent = false
    private var mTapListener: OnTapListener? = null
    private var mExitListener: OnExitListener? = null
    private var mActionMoveListener: OnActionMoveListener? = null

    init {
        initializePaint()
    }

    private fun initializePaint() {
        mPaint.color = Color.TRANSPARENT // 使用颜色资源
    }

    fun setBgAlpha(alpha: Int) {
        mAlpha = alpha
        invalidate()
    }

    override fun onDraw(canvas: Canvas) {
        mPaint.alpha = mAlpha
        canvas.drawRect(0f, 0f, mWidth.toFloat(), mHeight.toFloat(), mPaint)
        canvas.translate(mTranslateX, mTranslateY)
        canvas.scale(mScale, mScale, (mWidth / 2).toFloat(), (mHeight / 2).toFloat())
        super.onDraw(canvas)
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        mWidth = w
        mHeight = h
    }

    override fun dispatchTouchEvent(event: MotionEvent): Boolean {
        //only scale == 1 can drag
        if (scale == 1f) {
            when (event.action) {
                MotionEvent.ACTION_DOWN -> {
                    onActionDown(event)

                    //change the canFinish flag
                    canFinish = !canFinish
                }

                MotionEvent.ACTION_MOVE -> {

                    //in viewpager
                    if (mTranslateY == 0f && mTranslateX != 0f) {

                        //如果不消费事件，则不作操作
                        if (!isTouchEvent) {
                            mScale = 1f
                            return super.dispatchTouchEvent(event)
                        }
                    }

                    //single finger drag  down
                    if (mTranslateY >= 0 && event.pointerCount == 1) {

                        onActionMove(event)
                        //如果有上下位移 则不交给viewpager
                        if (mTranslateY != 0f) {
                            mActionMoveListener?.Move(true)
                            isTouchEvent = true
                        }
                        return true
                    }

                    //防止下拉的时候双手缩放
                    if (mTranslateY >= 0 && mScale < 0.95) {
                        return true
                    }
                }

                MotionEvent.ACTION_UP -> {//防止下拉的时候双手缩放
                    if (event.pointerCount == 1) {
                        onActionUp(event)
                        isTouchEvent = false
                        //judge finish or not
                        postDelayed({
                            if (mTranslateX == 0f && mTranslateY == 0f && canFinish) {
                                mTapListener?.onTap(this@DragPhotoView)
                            }
                            canFinish = false
                        }, 330)
                    }
                }
            }
        }
        return super.dispatchTouchEvent(event)
    }

    private fun onActionUp(event: MotionEvent) {
        if (mTranslateY > MAX_TRANSLATE_Y) {
            if (mExitListener != null) {
                mExitListener?.onExit(
                    this,
                    mTranslateX,
                    mTranslateY,
                    mWidth.toFloat(),
                    mHeight.toFloat()
                )
            } else {
                throw RuntimeException("DragPhotoView: onExitLister can't be null ! call setOnExitListener() ")
            }
        } else {
            performAnimation()
        }
    }

    private fun onActionMove(event: MotionEvent) {
        val moveY = event.y
        val moveX = event.x
        mTranslateX = moveX - mDownX
        mTranslateY = moveY - mDownY

        //保证上划到到顶还可以继续滑动
        if (mTranslateY < 0) {
            mTranslateY = 0f
        }
        val percent = mTranslateY / MAX_TRANSLATE_Y
        if (mScale in mMinScale..1f) {
            mScale = 1 - percent
            mAlpha = (255 * (1 - percent)).toInt()
            if (mAlpha > 255) {
                mAlpha = 255
            } else if (mAlpha < 0) {
                mAlpha = 0
            }
        }
        if (mScale < mMinScale) {
            mScale = mMinScale
        } else if (mScale > 1f) {
            mScale = 1f
        }
        invalidate()
    }

    private fun performAnimation() {
        getScaleAnimation().start()
        getTranslateXAnimation().start()
        getTranslateYAnimation().start()
        getAlphaAnimation().start()
    }

    private fun getAlphaAnimation(): ValueAnimator {
        val animator = ValueAnimator.ofInt(mAlpha, 255)
        animator.duration = DURATION
        animator.addListener(object : Animator.AnimatorListener {
            override fun onAnimationStart(animator: Animator) {}
            override fun onAnimationEnd(animator: Animator) {
                mActionMoveListener?.Move(false)
            }

            override fun onAnimationCancel(animator: Animator) {}
            override fun onAnimationRepeat(animator: Animator) {}
        })
        animator.addUpdateListener { valueAnimator ->
            mAlpha = valueAnimator.animatedValue as Int
        }
        return animator
    }

    private fun getTranslateYAnimation(): ValueAnimator {
        val animator = ValueAnimator.ofFloat(mTranslateY, 0f)
        animator.duration = DURATION
        animator.addUpdateListener { valueAnimator ->
            mTranslateY = valueAnimator.animatedValue as Float
        }
        return animator
    }

    private fun getTranslateXAnimation(): ValueAnimator {
        val animator = ValueAnimator.ofFloat(mTranslateX, 0f)
        animator.duration = DURATION
        animator.addUpdateListener { valueAnimator ->
            mTranslateX = valueAnimator.animatedValue as Float
        }
        return animator
    }

    private fun getScaleAnimation(): ValueAnimator {
        val animator = ValueAnimator.ofFloat(mScale, 1f)
        animator.duration = DURATION
        animator.addUpdateListener { valueAnimator ->
            mScale = valueAnimator.animatedValue as Float
            invalidate()
        }
        animator.addListener(object : Animator.AnimatorListener {
            override fun onAnimationStart(animation: Animator) {
                isAnimate = true
            }

            override fun onAnimationEnd(animation: Animator) {
                isAnimate = false
                animator.removeAllListeners()
            }

            override fun onAnimationCancel(animation: Animator) {
            }

            override fun onAnimationRepeat(animation: Animator) {
            }
        })
        return animator
    }

    private fun onActionDown(event: MotionEvent) {
        mDownX = event.x
        mDownY = event.y
    }

    fun getMinScale(): Float {
        return mMinScale
    }

    fun setMinScale(minScale: Float) {
        mMinScale = minScale
    }

    fun setOnTapListener(listener: OnTapListener?) {
        mTapListener = listener
    }

    fun setOnExitListener(listener: OnExitListener?) {
        mExitListener = listener
    }

    fun setOnActionMoveListener(listener: OnActionMoveListener?) {
        mActionMoveListener = listener
    }

    interface OnActionMoveListener {

        fun Move(p: Boolean)
    }

    interface OnTapListener {

        fun onTap(view: DragPhotoView?)
    }

    interface OnExitListener {

        fun onExit(view: DragPhotoView?, translateX: Float, translateY: Float, w: Float, h: Float)
    }

    fun finishAnimationCallBack() {
        mTranslateX = -mWidth / 2 + mWidth * mScale / 2
        mTranslateY = -mHeight / 2 + mHeight * mScale / 2
        invalidate()
    }

}